package edu.northwestern.cbits.purple_robot_manager.http;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.preference.PreferenceManager;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.MethodNotSupportedException;
import org.apache.http.entity.ContentProducer;
import org.apache.http.entity.EntityTemplate;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Locale;
import java.util.Scanner;
import edu.northwestern.cbits.purple_robot_manager.R;
import edu.northwestern.cbits.purple_robot_manager.RobotContentProvider;
import edu.northwestern.cbits.purple_robot_manager.config.JSONConfigFile;
import edu.northwestern.cbits.purple_robot_manager.config.SchemeConfigFile;
import edu.northwestern.cbits.purple_robot_manager.probes.Probe;
import edu.northwestern.cbits.purple_robot_manager.probes.ProbeManager;
public class ProbesHelpRequestHandler implements HttpRequestHandler
{
private Context _context = null;
public ProbesHelpRequestHandler(Context context)
{
super();
this._context = context;
}
public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException
{
if (BasicAuthHelper.isAuthenticated(request) == false)
{
BasicAuthHelper.unauthedResponse(response);
return;
}
String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST"))
throw new MethodNotSupportedException(method + " method not supported");
String target = request.getRequestLine().getUri();
String[] components = target.split("/");
String path = null;
if (components.length > 3)
path = components[3];
response.setStatusCode(HttpStatus.SC_OK);
response.setHeader("Access-Control-Allow-Origin", "*");
final byte[] content = this.fetchContent(this._context, path);
EntityTemplate body = new EntityTemplate(new ContentProducer()
{
public void writeTo(OutputStream out) throws IOException
{
ByteArrayInputStream in = new ByteArrayInputStream(content);
byte[] b = new byte[1024];
int read = 0;
while ((read = in.read(b, 0, b.length)) != -1)
out.write(b, 0, read);
out.close();
in.close();
}
});
response.setEntity(body);
}
private byte[] fetchContent(Context context, String path)
{
if (path == null)
{
try
{
JSONArray probes = new JSONArray();
for (Probe probeObj : ProbeManager.allProbes(context))
{
JSONObject probeDef = new JSONObject();
probeDef.put("name", probeObj.name(context));
probeDef.put("title", probeObj.title(context));
probeDef.put("summary", probeObj.summary(context));
probeDef.put("category", probeObj.probeCategory(context));
String assetPath = probeObj.assetPath(context);
if (assetPath != null)
probeDef.put("path", assetPath);
probes.put(probeDef);
}
AssetManager am = this._context.getAssets();
InputStream in = am.open("embedded_website/docs/probes_template.html");
// http://stackoverflow.com/questions/309424/read-convert-an-inputstream-to-a-string
Scanner s = new Scanner(in).useDelimiter("\\A");
String content = "";
if (s.hasNext())
content = s.next();
content = content.replace("{{ PROBES }}", probes.toString(2));
return content.getBytes(Charset.forName("UTF-8"));
}
catch (IOException | JSONException e)
{
e.printStackTrace();
}
return "404 ERROR".getBytes(Charset.forName("UTF-8"));
}
else
{
Probe probe = null;
for (Probe probeObj : ProbeManager.allProbes(context))
{
if (path.equals(probeObj.assetPath(context)))
probe = probeObj;
}
if (probe != null)
{
try
{
AssetManager am = this._context.getAssets();
InputStream in = am.open("embedded_website/docs/probe_template.html");
// http://stackoverflow.com/questions/309424/read-convert-an-inputstream-to-a-string
Scanner s = new Scanner(in).useDelimiter("\\A");
String content = "";
if (s.hasNext())
content = s.next();
s.close();
in = am.open("embedded_website/docs/probes/" + path);
s = new Scanner(in).useDelimiter("\\A");
String pageContent = "";
if (s.hasNext())
pageContent = s.next();
s.close();
content = content.replace("{{ PROBE_DOCUMENTATION }}", pageContent);
content = content.replace("{{ PROBE_NAME }}", probe.title(context));
content = content.replace("{{ PROBE_SUMMARY }}", probe.summary(context));
content = content.replace("{{ PROBE_PARAMETERS }}", probe.fetchSettings(context).toString(2));
content = content.replace("{{ SCHEME_CONFIG }}", SchemeConfigFile.probeConfig(probe.configuration(context)).toString());
content = content.replace("{{ JAVASCRIPT_CONFIG }}", JSONConfigFile.jsonFromMap(probe.configuration(context)).toString(2));
String where = "source = ?";
String[] args = { probe.name(context)};
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this._context);
boolean isAuthed = prefs.getString(LocalHttpServer.BUILTIN_HTTP_SERVER_PASSWORD, LocalHttpServer.BUILTIN_HTTP_SERVER_PASSWORD_DEFAULT).length() > 0;
if (isAuthed)
{
Cursor c = context.getContentResolver().query(RobotContentProvider.RECENT_PROBE_VALUES, null, where, args, "recorded DESC");
if (c.moveToNext())
{
JSONObject reading = new JSONObject(c.getString(c.getColumnIndex("value")));
content = content.replace("{{ LATEST_READING }}", reading.toString(2));
}
else
content = content.replace("{{ LATEST_READING }}", context.getString(R.string.error_no_latest_probe_value));
c.close();
}
else
content = content.replace("{{ LATEST_READING }}", context.getString(R.string.error_auth_required));
return content.getBytes(Charset.forName("UTF-8"));
}
catch (IOException | JSONException e)
{
e.printStackTrace();
}
}
}
return "404 ERROR".getBytes(Charset.forName("UTF-8"));
}
}